﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;

namespace DARE
{
#if !WINDOWS_PHONE

    public class CSound : ARenderable
    {

    #region fields

        private Cue m_cue;
        private string m_soundName;
        private AudioEmitter m_audioEmitter;
        private bool m_trigger;
        private CSoundMgr m_soundMgr;

    #endregion

    #region properties

        public Cue Cue
        {
            get { return m_cue; }
            set { m_cue = value; }
        }

        public AudioEmitter AudioEmitter
        {
            get { return m_audioEmitter; }
        }

        public bool IsTriggered
        {
            get { return m_trigger; }
            set { Play(); }
        }

        public string SoundName
        {
            get { return m_soundName; }
        }

    #endregion

    #region ctor

        public CSound()
        {
            Initialize(null, null);
        }

        /// <summary>
        /// If no soundname is specified, the name will be used as a soundname too.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="soundName"></param>
        public CSound(string name, string soundName)
        {
            if (soundName == null)
                soundName = name;
            Initialize(name, soundName);
        }

        private void Initialize(string name, string soundName)
        {
            if ((name == null) || (soundName == null))
                throw new Exception("Name or soundName NULL !");
            m_trigger = false;
            m_audioEmitter = new AudioEmitter();
            m_name = name;
            m_soundName = soundName;
            m_soundMgr = CDare.Instance.AudioMgr.SoundMgr;
            m_cue = m_soundMgr.SoundBank.GetCue(soundName);
            if (m_cue == null)
                throw new Exception("No sound \"" + soundName + "\" found !");
            m_soundMgr.AddSound(this);
        }

        public CSound Clone()
        {
            return new CSound(m_name, m_soundName);
        }

    #endregion

    #region run

        public override void Update(GameTime gameTime)
        {
            m_audioEmitter.Position = m_node.Position;
            //m_audioEmitter.Forward = m_node.GetLocalAxisZ();
            //m_audioEmitter.Up = 
            if (!m_cue.IsStopped && (m_trigger == true))
                Apply3D();
            else
                m_trigger = false;
        }

        public override void Draw(GameTime gameTime)
        {
            
        }

    #endregion

    #region method

        private void Apply3D()
        {
            AudioListener audioL = m_soundMgr.AudioListener;
            float distance = (audioL.Position - m_audioEmitter.Position).Length();

            m_cue.Apply3D(audioL, m_audioEmitter);
            m_cue.SetVariable("Distance", distance);
        }

        public void Play()
        {
            m_trigger = true;
            m_cue.Stop(AudioStopOptions.Immediate);
            m_cue = m_soundMgr.SoundBank.GetCue(m_soundName);
            Apply3D();
            m_cue.Play();
        }

        public void Stop()
        {
            m_trigger = false;
            m_cue.Stop(AudioStopOptions.Immediate);
        }

    #endregion

    #region attach/detach

        public CSound AttachToEntity(CEntity entity)
        {
            entity.AttachSound(this);
            return this;
        }

        public CSound DetachFromEntity()
        {
            m_entity.DetachSound();
            return this;
        }

    #endregion

    }
#endif
}
